function GM:HUDPaint() 
 	--hook powa
end

include ("helper_functions.lua")

local PANEL = {}
function PANEL:Init()
	self.Quad = {}
	self.Back = Color( 255, 255, 255 )
	self.Line = Color( 0, 0, 0 )
end
function PANEL:SetQuad( x1, w1, x2, w2 )
	self.Quad = Quad( x1, 0, w1, x2, 1, w2 )
end
function PANEL:Scale( quad )
	local w, h = self:GetSize()
	w, h = w - 1, h - 1
	local scaled = {}
	for i, pos in pairs( quad ) do
		scaled[ i ] = { x = pos.x * w, y = pos.y * h }
	end
	return scaled
end
function PANEL:GetCorner( num )
	local scaled = self:Scale( self.Quad )
	local corner = scaled[ num ]
	return self:LocalToScreen( corner.x, corner.y )
end
function PANEL:SetColour( back, line )
	self.Back = back or self.Back
	self.Line = line or self.Line
end
function PANEL:SetContent( func )
	self.Content = func
end

// Size/position.
function PANEL:SetSizeScale( w, h )
	self.SizeScale = { w, h }
	self:PerformLayout()
end
function PANEL:SetPosOffset( x, y )
	self.PositionOffset = { x, y }
	self:PerformLayout()
end
function PANEL:PerformLayout()
	local sh = ScrH()
	
	// Set the size relative to the screen.
	if ( self.SizeScale ) then
		self:SetSize( self.SizeScale[ 1 ] * sh, self.SizeScale[ 2 ] * sh )
	end
	
	// Set the position offset from the edges of the screen.
	if ( self.PositionOffset ) then
		local x, y = self.PositionOffset[ 1 ] * sh, self.PositionOffset[ 2 ] * sh
		
		local w, h = self:GetSize()
		if ( x < 0 ) then x = x - w end
		if ( y < 0 ) then y = y - h end
		
		x, y = x % ScrW(), y % sh
		self:SetPos( x, y )
	end
end
function PANEL:ShouldDraw( func )
	self.ShouldDrawFunc = func
end
function PANEL:Paint()
	local ply = LocalPlayer()
	if ( !IsValid( ply ) ) then return end
	
	if ( self.ShouldDrawFunc ) then
		local ok, error = pcall( self.ShouldDrawFunc, ply )
		if ( !ok ) then Error( error ) return end
		if ( error != true ) then return end
	end
	
	local quad = self:Scale( self.Quad )
	DrawQuad( quad, self.Back, self.Line )
	
	if ( self.Content ) then
		local w, h = self:GetSize()
		local ok, error = pcall( self.Content, GAMEMODE, self, w, h, ply )
		if ( !ok ) then Error( error ) end
	end
end
vgui.Register( "incursion.Quad", PANEL )


// #########################
// Flash
// Usage: Flash( name, value [, size ] )
// e.g Flash( "Health", health )
// #########################

local flash = {}
local function Flash( name, value, size )
	local info = flash[ name ]
	if ( info ) then
		if ( value != info.Value || !value ) then
			flash[ name ].Time = CurTime() + 0.5
		end
		if ( value ) then info.Value = value end
	else
		flash[ name ] = {
			Value = value,
			Time = CurTime()
		}
		info = flash[ name ]
	end
	
	return math.Clamp( ( info.Time - CurTime() ) / 0.5, 0, 1 ) * ( size or 3 )
end


// #########################
// Shield power + time
// #########################

function GM:HUDShieldPower( panel, w, h, ply )	
	local percent = math.ceil( ( self:GetRoundTimer() / self:GetRoundLength() ) * 100 )
	local text = "SHIELD POWER REMAINING"
	if ( self:IsFight() ) then
		text = "SHIELD POWER CHARGING"
		percent = 100 - percent
	end
	
	local x, y = w * 0.04, h * 0.07
	draw.SimpleText( text, SFTR30, x, y, HUD_TEXT_COLOUR )
	
	x, y = w * 0.24, h * 0.15
	draw.SimpleTextOutlined( percent .. "%", SFTR80, x, y, HUD_TEXT_COLOUR, _, _, Flash( "Shield Percent", percent ), HUD_TEXT_OUTLINE_COLOUR )
end
function GM:HUDEstimatedTime( panel, w, h, ply )
	local x, y = w * 0.2, h * 0.025
	draw.SimpleText( string.FormattedTime( math.ceil( self:GetRoundTimer() ), "%02i:%02i" ), SFTR50, x, y, HUD_TEXT_COLOUR)
	
	x, y = w * 0.11, h * 0.50
	draw.SimpleText( "ESTIMATED TIME", SFTR30, x, y, HUD_TEXT_COLOUR )
end


// #########################
// Credits
// #########################

function GM:HUDCredits( panel, w, h, ply )
	local credits = tostring( self:GetCredits() )
	credits = string.rep( "0", 5 - string.len( credits ) ) .. credits
	
	local x, y = w * 0.93, -5
	draw.SimpleTextOutlined( credits, SFTR80, x, y, HUD_TEXT_COLOUR, TEXT_ALIGN_RIGHT, _, Flash( "Credits", credits ), HUD_TEXT_OUTLINE_COLOUR )
	
	y = y + ( h * 0.6 )
	draw.SimpleText( "CREDITS", SFTR30, x, y, HUD_TEXT_COLOUR, TEXT_ALIGN_RIGHT )
end


// #########################
// Health
// #########################

function GM:HUDHealth( panel, w, h, ply )
	local health = ply:Health()
	local text, outline = HUD_TEXT_COLOUR, HUD_TEXT_OUTLINE_COLOUR
	if ( health < 25 ) then
		text, outline = HUD_TEXT_COLOUR_R, HUD_TEXT_OUTLINE_COLOUR_R
		if ( CurTime() > ( self.HealthFlash or 0 ) ) then
			Flash( "Health" )
			self.HealthFlash = CurTime() + 0.5
		end
	end
	
	local x, y = w / 20, h / 8
	draw.SimpleText( "HEALTH", SFTR30, x, y, text )
	
	x, y = x + ( w / 12 ), y + ( h / 12 )	
	draw.SimpleTextOutlined( health .. "%", SFTR80, x, y, text, _, _, Flash( "Health", health ), outline )
end


// #########################
// Ammo
// #########################

local function GetAmmo( ply )
	local weap = ply:GetActiveWeapon()
	if ( !IsValid( weap ) || !weap:IsWeapon() ) then return end
	
	local ammotype = weap:GetPrimaryAmmoType()
	if ( !ammotype || ammotype == -1 || ammotype == "" ) then return end
	
	local one, two = 0, -1
	// The weapon has mags.
	if ( weap:Clip1() > -1 ) then
		one = weap:Clip1()
		two = ply:GetAmmoCount( ammotype )
	else
		if weap.Ammo then
			one = weap:Ammo()
		else
			one = ply:GetAmmoCount( ammotype )
		end
	end
	
	return one, two
end
local function DrawAmmo( ply )
	local one, two = GetAmmo( ply )
	if ( !one && !two ) then return false end
	return true
end
function GM:HUDAmmo( panel, w, h, ply )
	local one, two = GetAmmo( ply )
	
	local text, outline = HUD_TEXT_COLOUR, HUD_TEXT_OUTLINE_COLOUR
	if ( one < 1 && two < 1 ) then
		text, outline = HUD_TEXT_COLOUR_R, HUD_TEXT_OUTLINE_COLOUR_R
		if ( CurTime() > ( self.AmmoFlash or 0 ) ) then
			Flash( "Ammo" )
			self.AmmoFlash = CurTime() + 0.5
		end
	end
	
	draw.SimpleText( "AMMUNITION", SFTR30, w / 10, h / 1.7, text )
	if ( two == -1 ) then
		panel:SetSizeScale( 0.2, 0.09 )
		draw.SimpleTextOutlined( one, SFTR80, w * 0.9, -5, text, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, Flash( "Ammo", one ), outline )
	else
		panel:SetSizeScale( 0.28, 0.09 )
		draw.SimpleTextOutlined( one, SFTR80, w * 0.63, -5, text, TEXT_ALIGN_RIGHT, TEXT_ALIGN_BOTTOM, Flash( "Ammo", one ), outline )
		draw.SimpleTextOutlined( "/" .. two, SFTR50, w * 0.63, 10, text, _, TEXT_ALIGN_BOTTOM, Flash( "Ammo", one ), outline )
	end
end

// #########################
// Round change
// #########################

GM.RoundChangeTime = -10

function GM:HUDRoundChange (panel, w, h, ply)
	local col = table.Copy (HUD_TEXT_COLOUR)
	local alpha = 200 + math.Clamp((GAMEMODE.RoundChangeTime - CurTime() + 8) * 200 / 2, -200, 0)
	local col2, col3 = table.Copy(HUD_BOX_COLOUR), table.Copy(HUD_LINE_COLOUR)
	col.a, col2.a, col3.a = alpha, alpha, alpha
	self.RoundChangeQuad:SetColour( col2, col3 )
	local txt1 = "THE SHIELDS ARE DOWN!"
	local txt2 = "FOR time, DEFEND AGAINST"
	local wavenum = self:GetRoundNumber()
	if self:IsBuild() then
		txt1 = "THE SHIELDS ARE NOW UP!"
		txt2 = "FOR time, PREPARE FOR"
		wavenum = wavenum + 1
	end
	local x, y = w / 32, h / 16
	draw.SimpleText( txt1, SFTR30, x, y, col )
	y = h * 3 / 16
	draw.SimpleText( string.gsub (txt2, "time", string.FormattedTime( math.ceil( self:GetRoundTimer() ), "%02i:%02i" )), SFTR50, x, y, col )
	x, y = w * 0.7, h * 0.40
	draw.SimpleText( "WAVE "..wavenum, SFTR80, x, y, col, TEXT_ALIGN_RIGHT )
end

function GM:HUDRoundChangeDetect ()
	self.RoundChangeTime = CurTime()
end

GM:AddHook ("RoundChanged", "HUDRoundChangeDetect")


// #########################
// Waves
// #########################

function GM:HUDWaves( panel, w, h, ply )
	local wave = math.floor(self:GetRoundNumber() / 2)
	local total = GetGlobalInt( "IncTotalWaves", 0 )
	local text = wave .. "/" .. total
	
	local x, y = w * 0.15, h * 0.07
	draw.SimpleText( "WAVE", SFTR30, x, y, HUD_TEXT_COLOUR, TEXT_ALIGN_LEFT )
	
	local x, y = w * 0.75, h * 0.15
	draw.SimpleTextOutlined( text, SFTR80, x, y, HUD_TEXT_COLOUR, TEXT_ALIGN_RIGHT, _, Flash( "Wave", wave ), HUD_TEXT_OUTLINE_COLOUR )
end

// #########################
// YOU WIN
// #########################

function GM:HUDWin( panel, w, h, ply )
	local top, first, second = "", "", "MAP RESTART IN " .. math.ceil( self:GetRoundTimer() ) .. " SECONDS"
	if ( GAMEMODE.GameWon == true ) then
		top, first = "WELL DONE!", "YOU HAVE SURVIVED!"
	elseif ( GAMEMODE.GameWon == false ) then
		//top, first = "YOU LOSE", "GOOD DAY SIR!"
		top, first = "DEFEATED", "ALL GENERATORS DESTROYED"
	end
	
	local x, y = w * 0.02, h * -0.05
	draw.SimpleText( top, SFTR80, x, y, HUD_TEXT_COLOUR )
	y = y + ( h * 0.45 )
	
	draw.SimpleText( first, SFTR50, x, y, HUD_TEXT_COLOUR )
	y = y + ( h * 0.22 )
	
	draw.SimpleText( second, SFTR50, x, y, HUD_TEXT_COLOUR )
end

// #########################
// Quad Initialization
// #########################

function GM:CreateHUD()
	self.ShieldPowerQuad = vgui.Create( "incursion.Quad" )
		self.ShieldPowerQuad:SetPosOffset( HUD_INSET, HUD_INSET )
		self.ShieldPowerQuad:SetSizeScale( 0.3, 0.09 )
		self.ShieldPowerQuad:SetQuad( 0, 1, 0, 0.8 )
		self.ShieldPowerQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.ShieldPowerQuad:SetContent( self.HUDShieldPower )
		
	self.TimeQuad = vgui.Create( "incursion.Quad" )
		// Put it next to the shield power quad.
		local x, y = self.ShieldPowerQuad:GetCorner( QUAD_TOPRIGHT )
		self.TimeQuad:SetPosOffset( ( x / ScrH() ) - 0.02, HUD_INSET )
		self.TimeQuad:SetSizeScale( 0.26, 0.075 )
		self.TimeQuad:SetQuad( 0.19, 0.81, 0, 0.81 )
		self.TimeQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.TimeQuad:SetContent( self.HUDEstimatedTime )
		
	self.CreditsQuad = vgui.Create( "incursion.Quad" )
		self.CreditsQuad:SetPosOffset( -HUD_INSET, HUD_INSET )
		self.CreditsQuad:SetSizeScale( 0.23, 0.09 )
		self.CreditsQuad:SetQuad( 0, 1, 0.25, 0.75 )
		self.CreditsQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.CreditsQuad:SetContent( self.HUDCredits )
		
	self.HealthQuad = vgui.Create( "incursion.Quad" )
		self.HealthQuad:SetPosOffset( HUD_INSET, -HUD_INSET )
		self.HealthQuad:SetSizeScale( 0.22, 0.09 )
		self.HealthQuad:SetQuad( 0, 0.75, 0, 1 )
		self.HealthQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.HealthQuad:ShouldDraw( function( ply ) return self:IsFight() && ply:Alive() end )
		self.HealthQuad:SetContent( self.HUDHealth )
		
	self.AmmoQuad = vgui.Create( "incursion.Quad" )
		self.AmmoQuad:SetPosOffset( -HUD_INSET, -HUD_INSET )
		self.AmmoQuad:SetSizeScale( 0.22, 0.09 )
		self.AmmoQuad:SetQuad( 0.22, 0.78, 0, 1 )
		self.AmmoQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.AmmoQuad:ShouldDraw( DrawAmmo )
		self.AmmoQuad:SetContent( self.HUDAmmo )
		
	self.RoundChangeQuad = vgui.Create( "incursion.Quad" )
		self.RoundChangeQuad:SetPosOffset( 0.5,	0.12 )
		self.RoundChangeQuad:SetSizeScale( 0.58, 0.12 )
		self.RoundChangeQuad:SetQuad( 0, 0.8, 0, 1 )
		self.RoundChangeQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.RoundChangeQuad:ShouldDraw( function () return GAMEMODE.RoundChangeTime + 10 > CurTime() && GAMEMODE.GameWon == nil end )
		self.RoundChangeQuad:SetContent( self.HUDRoundChange )
		
	self.WaveQuad = vgui.Create( "incursion.Quad" )
		self.WaveQuad:SetPosOffset( -HUD_INSET - 0.18, HUD_INSET )
		self.WaveQuad:SetSizeScale( 0.23, 0.09 )
		self.WaveQuad:SetQuad( 0, 0.75, 0.25, 0.75 )
		self.WaveQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.WaveQuad:ShouldDraw( function() return GetGlobalInt( "IncTotalWaves" ) > 0 end )
		self.WaveQuad:SetContent( self.HUDWaves )
		
	self.WinQuad = vgui.Create( "incursion.Quad" )
		self.WinQuad:SetPosOffset( 0.5,	0.12 )
		self.WinQuad:SetSizeScale( 0.58, 0.12 )
		self.WinQuad:SetQuad( 0, 0.8, 0, 1 )
		self.WinQuad:SetColour( HUD_BOX_COLOUR, HUD_LINE_COLOUR )
		self.WinQuad:ShouldDraw( function () return GAMEMODE.GameWon != nil end )
		self.WinQuad:SetContent( self.HUDWin )

	INCURSION_HUD_QUADS = {
		self.ShieldPowerQuad,
		self.TimeQuad,
		self.CreditsQuad,
		self.HealthQuad,
		self.AmmoQuad,
		self.RoundChangeQuad,
		self.WaveQuad,
		self.WinQuad
	}
end
GM:AddHook( "Initialize", "CreateHUD" )

function GM:RefreshHUD()
	for _, panel in pairs(INCURSION_HUD_QUADS or {}) do
		panel:Remove()
	end

	self:CreateHUD()
end
GM:AddHook( "OnReloaded", "RefreshHUD" )

local TargetName = "NIL"
local TargetHP = 0
local TargetMaxHP = 0
local LastSighted = -1

function GM:DrawTargetID ()
	local trc = util.QuickTrace (LocalPlayer():GetShootPos(), LocalPlayer():GetAimVector() * 512, LocalPlayer())
	if trc.HitNonWorld then
		if trc.Entity:IsPlayer() then
			TargetHP = trc.Entity:Health()
			TargetMaxHP = 100
			TargetName = trc.Entity:Nick()
			LastSighted = CurTime()
		else
			TargetHP = trc.Entity:GetPropHealth()
			TargetMaxHP = trc.Entity:GetPropMaxHealth()
			if ( trc.Entity.TargetID ) then
				local ok, text = pcall( trc.Entity.TargetID, trc.Entity, TargetHP, TargetMaxHP )
				if ( ok && text != nil ) then
					TargetHP = text
				end
			end
			TargetName = trc.Entity.TargetIDName-- or trc.Entity:GetClass()
			LastSighted = CurTime()
		end
	end
	
	if CurTime() - LastSighted > 0.2 then return end
	
	local boxCol = c( HUD_BOX_COLOUR )
	local fillCol = c( HUD_TEXT_COLOUR )
	--local outCol = c( HUD_TEXT_OUTLINE_COLOUR )
	
	local x,y = ScrW() * 0.5, ScrH() * 0.55
	local w,h = ScrW() * 0.2, ScrW() * 0.02
	local w2,h2 = w - ScrW() * 0.005, h - ScrW() * 0.005
	
	if ( TargetHP != nil ) then
		if type( TargetHP ) == "number" then
			if ( TargetHP > 0 ) then
				surface.SetDrawColor (fillCol.r, fillCol.g, fillCol.b, fillCol.a)
				surface.DrawRect (x - w * 0.5, y, w, h)
				surface.SetDrawColor (boxCol.r, boxCol.g, boxCol.b, boxCol.a)
				surface.DrawRect (x - w2 * 0.5, y + (h - h2) * 0.5, w2 * TargetHP / TargetMaxHP, h2)
			end
		else
			draw.SimpleTextOutlined (string.upper(TargetHP), SFTR50, x, y, boxCol, TEXT_ALIGN_CENTER, nil, 2, fillCol)
		end
		y = y + h
	end
	
	if TargetName then
		draw.SimpleTextOutlined (string.upper(TargetName), SFTR50, x, y, boxCol, TEXT_ALIGN_CENTER, nil, 2, fillCol)	
	end
end

GM:AddHook( "HUDPaint", "DrawTargetID" )

function GM:DrawTargetID()
	local ply = LocalPlayer()
	if !IsValid(ply) then return end
	local trace = util.QuickTrace(ply:GetShootPos(), ply:GetAimVector() * 512, ply)
	if !IsValid(trace.Entity) then return end
	local ent = trace.Entity
	
	local lines = {}
	if ent:IsPlayer() then
		lines = {
			ent:Nick(),
			ent:Health() / 100
		}
	elseif ent.TargetID then
		local ret = {pcall(ent.TargetID, ent, ent:GetPropHealth(), ent:GetPropMaxHealth())}
		if ret[1] then
			table.remove(ret, 1)
			lines = ret
		else
			ErrorNoHalt(ret[2])
		end
	else
		local maxHP = ent:GetPropMaxHealth()
		if maxHP > 0 then
			local HP = ent:GetPropHealth()
			lines = {HP / maxHP}
		end
	end
	
	if ent.TargetIDName then
		table.insert(lines, ent.TargetIDName)
	end
	
	if #lines > 0 then
		local x, y = ScrW() * 0.5, ScrH() * 0.55
		local w, h = ScrW() * 0.2, ScrW() * 0.02
		local bw, bh = ScrW() / 400, ScrW() / 400 // Border width/height for bars.
		for _, line in pairs(lines) do
			if type(line) == "string" then
				draw.SimpleTextOutlined(line, SFTR50, x, y - 10, HUD_BOX_COLOUR, TEXT_ALIGN_CENTER, nil, 2, HUD_TEXT_COLOUR)
			elseif type(line) == "number" && line <= 1 then
				local o, f = HUD_TEXT_COLOUR, HUD_BOX_COLOUR
				local lx = x - (w / 2)
				surface.SetDrawColor(o.r, o.g, o.b, o.a)
				surface.DrawRect(lx, y, w, h)
				surface.SetDrawColor(f.r, f.g, f.b, f.a)
				surface.DrawRect(lx + bw, y + bh, (w - (bw * 2)) * line, h - (bh * 2))
			else
				draw.SimpleTextOutlined("-ERROR-", SFTR50, x, y - 10, HUD_BOX_COLOUR, TEXT_ALIGN_CENTER, nil, 2, HUD_TEXT_COLOUR)
			end
			y = y + h + 6
		end
	end
end
function GM:OverrideDefaultHealthAmmo (name)
	if name == "CHudHealth" or name == "CHudBattery" or name == "CHudAmmo" or name == "CHudSecondaryAmmo"--[[ or name == "CHudCrosshair"]] then return false end
end
GM:AddHook ("HUDShouldDraw", "OverrideDefaultHealthAmmo")

--credits popup (points appear over heads when you kill enemies, for example)

local credPopups = {}

function GM:AddCreditPopup (vec, amt)
	table.insert (credPopups, {
		RealTime(),
		vec,
		amt
	})
end

local fadeTime = 0.8

function GM:DrawCreditPopups ()	
	local textCol = c( HUD_TEXT_OUTLINE_COLOUR )
	local outCol = c( HUD_TEXT_COLOUR )
	
	for k,v in pairs (credPopups) do
		local specFadeTime = fadeTime * math.sqrt(math.sqrt(v[3] / 50))
		if v[1] + specFadeTime < RealTime() then --if time has expired
			credPopups[k] = nil
		else
			local text = tostring(v[3])
			if not string.find (text, "-") then text = "+"..text end
			local alpha = (specFadeTime + v[1] - RealTime()) * 200 / specFadeTime
			--printd (alpha)
			local col = table.Copy(textCol)
			local col2 = table.Copy(outCol)
			col.a, col2.a = alpha, alpha
			
			if v[2] then
				--get on-screen location
				local screenVec = v[2]:ToScreen()
				draw.SimpleTextOutlined (text, SFTR50, screenVec.x, screenVec.y - (RealTime() - v[1]) * S( 0.06 ), col, 1, nil, 1, col2)
			elseif ( self.CreditsQuad != nil ) then
				local x, y = self.CreditsQuad:GetCorner( QUAD_TOPLEFT )
				draw.SimpleTextOutlined (text, SFTR80, x + S( 0.04 ), y + S( 0.02 ) + (RealTime() - v[1]) * S( 0.06 ), col, nil, nil, 1, col2)
			end
		end
	end
end

GM:AddHook ("HUDPaint", "DrawCreditPopups")